package screen;

import game.FontLoader;
import java.awt.event.KeyEvent;
import org.lwjgl.input.Keyboard;
import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.Color;

public class CaixaTexto extends ObjetoTela {

    private Texto texto;
    private Box conteiner;
    private int movCursor, posCursor;//, fimSelecao;
    private TipoInput input;
    
    public enum TipoInput {
        NATURAL, INTEIRO, REAL, REAL_POSITIVO, FILE_PATH, TEXTO;
        
        public boolean valid(char c) {
            switch (this) {
                case NATURAL: return (c >= '0' && c <= '9');
                case INTEIRO: return (c >= '0' && c <= '9') || c == '-';
                case REAL:  return (c >= '0' && c <= '9') || c == '-' || c == '.';
                case REAL_POSITIVO:  return (c >= '0' && c <= '9') || c == '.';
                case FILE_PATH: return c != '\\' && c != '/' && c != '?' && c != '!' && c != '\'' && c != '"';
                default: return true; //TEXTO
            }
        }
    }
    
    public CaixaTexto(int x, int y, String textoInicial, int widthMinima) {
        this(x, y, textoInicial, widthMinima, TipoInput.TEXTO);
    }

    public CaixaTexto(int x, int y, String textoInicial, int widthMinima, TipoInput input) {
        super(x, y);
        this.posCursor = 0;
        this.texto = new Texto(x + 5, y, textoInicial, FontLoader.TEXT_BIG, Color.black);
        this.movCursor = this.texto.setMonospaced(true);
        this.conteiner = new Box(x, y, widthMinima, 30, Box.TEXTO);
        this.input = input;
    }

    public void setTexto(String texto) {
        this.texto.setTexto(texto);
        this.posCursor = (this.posCursor == -1 ? -1 : texto.length());
    }

    public String getTexto() {
        return this.texto.getTexto();
    }
    
    public boolean validate() {
        if (input == TipoInput.FILE_PATH || input == TipoInput.TEXTO)
            return true;
        try {
            double d = Double.parseDouble(texto.getTexto());
            if (input == TipoInput.REAL)
                return true;
            if (input == TipoInput.REAL_POSITIVO)
                return d >= 0;
            if (d != Math.floor(d))
                return false;
            return !(input == TipoInput.NATURAL && d < 0);
        } catch (NumberFormatException ex) {
            return false;
        }
    }
    
    public void parse(int codigo, char c) {
        switch(codigo) {
            case Keyboard.KEY_BACK:
                removerUltimo();
                break;
            case Keyboard.KEY_DELETE:
                removerAnterior();
                break;
            case Keyboard.KEY_HOME:
                irAoComeco();
                break;
            case Keyboard.KEY_END:
                irAoFinal();
                break;
            case Keyboard.KEY_RIGHT:
                moverCursorDireita();
                break;
            case Keyboard.KEY_LEFT:
                moverCursorEsquerda();
                break;
            default: //print out
                if (isPrintable(c)) {
                    if (input.valid(c)) {
                        if ((input == TipoInput.INTEIRO || input == TipoInput.REAL) && c == '-' && (posCursor != 0 || texto.getTexto().contains("-"))) //minus sign can only be put on the first position
                            return;
                        if ((input == TipoInput.REAL || input == TipoInput.REAL_POSITIVO) && c == '.' && texto.getTexto().contains(".")) //can only have one .
                            return;
                        addTexto(c);
                    }
                }
        }
    }
    
    public boolean isPrintable(char c) {
        Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
        return (!Character.isISOControl(c)) && c != KeyEvent.CHAR_UNDEFINED && block != null && block != Character.UnicodeBlock.SPECIALS;
    }

    public void addTexto(char c) {
        if (posCursor != -1) {
            String txt = this.texto.getTexto();
            this.texto.setTexto(txt.substring(0, posCursor) + c + txt.substring(posCursor));
            posCursor++;
        }
    }

    public void addTexto(String texto) {
        if (posCursor != -1) {
            String txt = this.texto.getTexto();
            this.texto.setTexto(txt.substring(0, posCursor) + texto + txt.substring(posCursor));
            posCursor++;
        }
    }

    public void moverCursorDireita() {
        if (this.posCursor < texto.getTexto().length() && this.posCursor != -1)
            this.posCursor++;
    }

    public void moverCursorEsquerda() {
        if (this.posCursor > 0)
            this.posCursor--;
    }

    public void setFocado() {
        this.posCursor = texto.getTexto().length();
    }

    public void setDesfocado() {
        this.posCursor = -1;
    }

    public void removerUltimo() {
        if (posCursor > 0) {
            String txt = this.texto.getTexto();
            this.texto.setTexto(txt.substring(0, posCursor - 1) + txt.substring(posCursor));
            this.posCursor--;
        }
    }

    public void removerAnterior() {
        if (posCursor < texto.getTexto().length() && posCursor != -1) {
            String txt = this.texto.getTexto();
            this.texto.setTexto(txt.substring(0, posCursor) + txt.substring(posCursor + 1));
        }
    }

    public void irAoComeco() {
        posCursor = 0;
    }

    public void irAoFinal() {
        if (posCursor != -1 && posCursor < texto.getTexto().length())
            posCursor = texto.getTexto().length();
    }

    @Override
    public void desenhar() {
        conteiner.desenhar();
        texto.desenhar();
        
        //Desenhar seletor
        glBindTexture(GL_TEXTURE_2D, 0);
        glColor3f(0, 0, 0);
        glBegin(GL_QUADS);
        {
            glVertex2f(x + 5 + posCursor * this.movCursor, y + 2);
            glVertex2f(x + 5 + posCursor * this.movCursor, y + 28);
            glVertex2f(x + 7 + posCursor * this.movCursor, y + 28);
            glVertex2f(x + 7 + posCursor * this.movCursor, y + 2);
        }
        glEnd();
        glColor3f(255, 255, 255);
    }
}